package core1;

import java.util.ArrayList;
import java.util.List;

import org.gicentre.utils.move.ZoomPan;

import processing.core.PApplet;

// global variables, singleton 

public class Globals {

	
	// Object references
	private static Globals instance;
	private PApplet parent;
	public ZoomPan zoomer;
	public Main mainRef;
	
	//display hardware settings
	public int displayWidth =1024;
	public int displayHeight =768;
	public boolean fullscreen = false;
	
	// Main configuration parameters
	public static final float radius = 1500f;
	public float scale;
	public int bigM = 16;
	public long maxKey = (long) Math.pow(2,bigM); 
	public int fingerUpdateFrequency=10;
	
	// display settings 
	public boolean drawFullFingerTables = false;
	public boolean drawPreds = false;
	public boolean drawText = false;
	public boolean drawLegend = false ;
	public boolean logicView = false;
	public float textSize = 10;
	public float nodeSize = 16;
	public float curvature = 0.1f;    //bezier curve "curviness"
	public float predCurvature = 0.5f;
	
	
	// Query animation parameters
	
	public boolean drawAlgo =false;
	public StandAloneChordNode targetNode = null;
	public static final int BALL = 1;
	public static final int LINE = 2;
	public static final int NOTHING = 0;
	public float queryBallRadius = 10;	
	public boolean animateQueries = true;
	public int queryLatency = 60; // Time it takes for a query to complete (simulation frames @ 60 fps)
	public int animateOnCurve = BALL; 
	public boolean HighlightCurrentPathSection = true;
	public boolean DrawStaticPathWhileAnimating = true;
	public int queryColor;
	public int queryOpacity = 80;
	public int querySpeed = 2; // time units elapsed at each frame
	public int queryMaxSpeed = 5;
	public int querySpeedChangeIncrement = 1;
	

	// color values
	public int BGColor = 0;
	public int TextColor = 0;
	public int RingColor = 0;
	public int NodeColor = 0;
	public int SelectedNodeColor = 0;
	public int NodeFrameColor = 0;
	public int SelectedNodeFrameColor = 0;
	
	public int ElementColor = 0;
	public int ElementFrameColor = 0;
	public int SelectedFingerColor = 0;
	public int FingerColor = 0;
	public int PredColor = 0;
	public int SelectedPredColor = 0;
	
	public static final int DARK 			= 0;
	public static final int LIGHT 			= 1;
	
	public static final int SIMPLE_MODE    = 0;
	public static final int MESH_MODE 	= 1;
	public static final int CHORD_MODE 	= 2;
	public static final int NETWORK_MODE_COUNT = 3;
	public int networkMode = SIMPLE_MODE;
	public int[] ColorThemes = new int[] {LIGHT, DARK};
	public int ColorThemeIndex = DARK;
	public int ringOpacity = 255;
	public int targetNodeHintColor = 0;
	public float statusSize=15; 




	


	public void setupColors() {
		int ColorTheme = ColorThemes[ColorThemeIndex];
		
		switch (ColorTheme) {
		case DARK:
			ringOpacity = 255;
			this.queryColor = parent.color(255,0,47);
			this.FingerColor = parent.color(13,100,220,128);
			this.SelectedFingerColor = parent.color(255, 00, 00);
			this.PredColor = parent.color(50,250,50);
			this.SelectedPredColor = parent.color(200,200,0);
			
			this.NodeColor = parent.color(10,35,231,200);
			this.SelectedNodeColor = parent.color(255,0,0,200);
			
			this.NodeFrameColor = parent.color(150,150,250);
			this.SelectedNodeFrameColor = parent.color(150,150,250);
			
			this.BGColor = parent.color(50,50,50);
			this.RingColor = parent.color(160, 160, 160,ringOpacity);
			this.TextColor = parent.color(255,255,255);
		
			this.ElementColor = parent.color(12,244,1);
			this.ElementFrameColor = parent.color(150,150,250);
			this.targetNodeHintColor = parent.color(150,150,150);
			
			break;
		case LIGHT:
			
			queryOpacity= 120;
			this.queryColor = parent.color(255,0,47);
			
			this.FingerColor = parent.color(13,100,220,128);
			this.SelectedFingerColor = parent.color(255, 00, 00);
			this.PredColor = parent.color(0,150,0);
			this.SelectedPredColor = parent.color(200,150,0);
			
			this.NodeColor = parent.color(10,35,231,200);
			this.SelectedNodeColor = parent.color(255,0,0,200);
			
			this.NodeFrameColor = parent.color(50,50,100);
			this.SelectedNodeFrameColor = parent.color(50,50,100);
			
			this.BGColor = parent.color(255,255,255); // For maximum contrast on the whiteboard
			this.RingColor = parent.color(10, 10, 10,ringOpacity);
			this.TextColor = parent.color(0,0,0);
		
			this.ElementColor = parent.color(12,160,12);
			this.ElementFrameColor = parent.color(50,50,100);
			this.targetNodeHintColor = parent.color(150,150,150);
			
			break;
		default:
			
		}
		
	}

	public void setParent(PApplet parent) {
		this.parent = parent;
	}

	public void setMain(Main mainRef) {
		
		this.mainRef = mainRef;
	}
	
	private Globals( PApplet parent){
		instance = this;
		this.parent = parent;
		this.setupColors();
	}
	
	public static Globals getInstance(){

		return instance;
	
	}
	
	public static Globals createInstance(PApplet parent){
		instance = new Globals(parent);
		return instance;
	}
	
public static boolean	interval_check_exc_exc(long Low, Long Mid, long High) {
    return ((Low < Mid) && (Mid < High)) ||
    ((High < Low) && (Low < Mid)) ||
    ((Mid < High) && (High < Low));}

public static boolean interval_check_inc_exc(long  Low,long Mid,long High) {
	return ((Low <= Mid) && (Mid < High)) ||
    ((High < Low) && (Low <= Mid)) ||
    ((Mid < High) && (High < Low)); }

 public static boolean interval_check_exc_inc(long Low,long Mid,long High) {
	return ((Low < Mid) && (Mid <= High)) ||
    ((High < Low) && (Low < Mid)) ||
    ((Mid <= High) && (High < Low));}

    public static boolean interval_check_inc_inc( long Low,long Mid,long High) {
	return ((Low <= Mid) && (Mid <= High)) ||
    ((High < Low) && (Low <= Mid)) ||
    ((Mid <= High) && (High < Low));}

	public int setOpacity(int color, int opacity){
		return parent.color(parent.red(color),parent.green(color),parent.blue(color),opacity);
		
	}
	public float getRingPosition(long key) {
return ((float)key /(float)maxKey) *360f ;
	}
	
	public float getRingPositionX(long key) {
return (float) radius* (float) Math.cos(Math.toRadians(getRingPosition(key)));
	}
	public float getRingPositionY(long key) {
return (float) radius* (float) Math.sin(Math.toRadians(getRingPosition(key)));
	}
	
	

}
